/*
 * @Descripttion:
 * @version: V1.0
 * @Author: ZYP
 * @Date: 2025-05-15 10:28:09
 * @LastEditors: ZYP
 * @LastEditTime: 2025-11-06 14:44:10
 */
#include "stdio.h"
#include "zyp_usb.h"
#include "esp_log.h"
#include "esp_err.h"
//  #include "tusb.h"
#include "tinyusb.h"
#include "tusb_cdc_acm.h" //.h has been include
#include "esp_timer.h"
#include "esp_psram.h"
#include "esp_task_wdt.h"
#include "zyp_log.h"
#include "mmc.h"

#if VIGINAL_MODE_HARD_STARTBIT_NO_FILE_SIZE
Virigin_File_Size_T virigin_file_size_t = {0, 0, 0, 0, 0};
#endif
// uint8_t *rx_buf;            ///recive buffer
uint8_t *psram_base = NULL;       /// POINT PSRAM ADDR
uint32_t current_file_index = 0;  /// curenrt recive file index
size_t totall_bytes_received = 0; /////current recive file size
size_t totall_bytes_received_data = 0;
static size_t debug_file_size = 0;
bool receiving_file = false;
bool usb_data_send_flag = false;
uint32_t expected_end_marker = 0;
size_t bytes_read = 0;

static uint8_t *dst = NULL;
static const char *TAG = "zyp_usb";
uint32_t front_4Byte = 0;
USB_CDC_MODE usb_mode;
// QueueHandle_t usb_cmd__queue = NULL;
QueueHandle_t usb_data_queue = NULL;
size_t data_cmd_cnt = 0;
uint8_t *cmd_data = NULL;
QueueHandle_t usb_cmd_queue = NULL;
#if IS_ENABLE_FACTORY_MODE_PROCESS
QueueHandle_t usb_factory_mode_queue = NULL;
#endif
bool host_connected = false;

#if IS_FILE_DEBUG
uint32_t debugbin_file_index_startbit = 0;
#endif

#if IS_EN_SEMAPHORE
SemaphoreHandle_t xInitSemaphore = NULL; /// SemaphoreHandle_t  actrully  QueueDefinition*   equal in value  SemaphoreHandle_t
#endif

#if IS_FILE_DEBUG
bool debugbinfile_reciveover = false;
uint32_t debug_file_index_startbit = 0;
#endif
#if IS_FFU_MDDE
bool ffu_binfile_reciveover = false;
uint32_t ffu_file_index_startbit = 0;
#endif

void USB_CMD_TASK(void *pvParameters)
{
#if IS_EN_SEMAPHORE
    /// WATING  Semaphore FREE
    if (xSemaphoreTake(xInitSemaphore, 1000 / portTICK_PERIOD_MS) != pdTRUE)
    {
        // ZYP_DEBUG_USB("USB_CMD_TASK Semaphore take fail\n");
        // return;
        // vTaskDelay(pdMS_TO_TICKS(50));
    }
#endif
    while (1)
    {
        // if (card == NULL || cmd == NULL)
        if (card == NULL) /// must detect!!!
        {
            ZYP_DEBUG_USB("USB_CMD_TASK CRAD OR CMD IS NULL\n");
            // return;                                                                                                                                                          ///once in  FreeRTOS  return，this task will be deleted?
            // vTaskDelay(pdMS_TO_TICKS(1000));
            vTaskDelay(pdMS_TO_TICKS(50));
            continue;
        }
        // ZYP_DEBUG_USB("card init done\n");
#if IS_ENABLE_USB_CMD_HANLDE
        // if (xQueueReceive(usb_debug_queue, &rwRecivebuffer, portMAX_DELAY) == pdTRUE)
        // {
        //     struct RequestBuffer *requestbuffer_p = (struct RequestBuffer *)&rwRecivebuffer;
        //     ZYP_DEBUG_USB("startBit: %d ,cmdId: %d  endbit: %d\n", requestbuffer_p->startBit, requestbuffer_p->cmdId, requestbuffer_p->endBit);
        // }
        if (xQueueReceive(usb_cmd_queue, &requestbuffer, 0) == pdTRUE)
        {
            ZYP_DEBUG_USB("startBit: %0x ,cmdId: %x,parm:%0x endbit: %x\n", requestbuffer.startBit, requestbuffer.cmdId, requestbuffer.cmdParm, requestbuffer.endBit);
            /// tofo Different cmd processing, let's ignore it for now.
            zyp_handle_cmd_fream(&requestbuffer, &responsebuffer, card, cmd);
        }
#if IS_ENABLE_FACTORY_MODE_PROCESS
        if (xQueueReceive(usb_factory_mode_queue, &factory_mode_t, 0) == pdTRUE)
        {
            ZYP_DEBUG_USB("factory_mode_t.factory_mode_starbit = %x\n", factory_mode_t.factory_mode_starbit);
            zyp_finall_tinyusb_cdcacm_write_queue(TINYUSB_CDC_ACM_0, (const uint8_t *)&factory_mode_t, sizeof(FactoryMode_T));
        }
#endif
#endif
        // vTaskDelay(pdMS_TO_TICKS(1000));
        vTaskDelay(pdMS_TO_TICKS(50));
    }
}

uint32_t convert_to_big_endian(uint32_t value)
{
    return ((value >> 24) & 0xFF) | ((value >> 8) & 0xFF00) | ((value << 8) & 0xFF0000) | ((value << 24) & 0xFF000000);
}

/**
 * @name:
 * @msg:
 * @param {int} fileIndex
 * @return {*}
 */
void zyp_send_file_via_usb(int fileIndex)
{
    if (!psram_base)
    {
        ESP_LOGE(TAG, "psram_base not allocated");
        return;
    }
    uint8_t *file_start = psram_base + fileIndex * FILE_SLOT_SIZE;
#if N0_USB_FIEL_SEND
    uint8_t byte1 = file_start[0];
    uint8_t byte2 = file_start[1];
    uint8_t byte3 = file_start[2];
    uint8_t byte4 = file_start[3];
    ZYP_DEBUG_USB("Bytes starting at file_start: %02x %02x %02x %02x\n", byte1, byte2, byte3, byte4);
    uint32_t condition = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
    ZYP_DEBUG_USB("Condition: %08x\n", condition);
#endif

#if USB_FIEL_SEND
    uint32_t condition = *(uint32_t *)file_start;
    ZYP_DEBUG_USB("current_file_index :%ld\n", current_file_index);
    ZYP_DEBUG_USB("fileIndex :%d\n", fileIndex);

    ZYP_DEBUG_USB("addr psram_base:%p, addr file_start: %p\n", psram_base, file_start);
    ZYP_DEBUG_USB("Condition: %08lx\n", condition);

    if (condition == LLF_FILE_START_4BIT || condition == DNLD_FILE_START_4BIT || condition == MAIN_FILE_START_4BIT)
    {
        size_t file_size;
        switch (fileIndex)
        {
            ZYP_DEBUG_USB("switch fileIndex :%d\n ", fileIndex);
        case LLF_FILE:
            file_size = LLF_FILE_SIZE;
            break;
        case DNLD_FILE:
            file_size = DNLD_FILE_SIZE;
            break;
        case MAIN_FILE:
            file_size = MAIN_FILE_SIZE;
            break;
        default:
            ESP_LOGE(TAG, "Invalid file index: %d", fileIndex);
            return;
        }
        ESP_LOGI(TAG, "Sending file %d via USB-CDC...", fileIndex);
        ZYP_DEBUG_USB("Sending file %d via USB-CDC...\n", fileIndex);

        //// every time send  1024 byte  restrict by subject to underling buffer
        const size_t chunk_size = 1024;
        size_t remaining = file_size;
        uint8_t *ptr = file_start;
        while (remaining > 0)
        {
            ZYP_DEBUG_USB("remaining %d bytes...\n", remaining);
            size_t to_send = (remaining > chunk_size) ? chunk_size : remaining;

            //// write queen
            size_t queued = tinyusb_cdcacm_write_queue(TINYUSB_CDC_ACM_0, ptr, to_send);
            if (queued != to_send)
            {
                ESP_LOGW(TAG, "Only %zu of %zu bytes queued", queued, to_send);
            }

            //// flush buffer block wait max 100ms
            esp_err_t err = tinyusb_cdcacm_write_flush(TINYUSB_CDC_ACM_0, pdMS_TO_TICKS(100));
            if (err != ESP_OK)
            {
                ESP_LOGE(TAG, "Failed to flush data over USB: %s", esp_err_to_name(err));
                return;
            }
            ptr += to_send;
            remaining -= to_send;
            vTaskDelay(pdMS_TO_TICKS(10));
        }
        ESP_LOGI(TAG, "File %d sent via USB-CDC successfully.", fileIndex);
    }
#endif
}

void tinyusb_cdc_line_state_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_t *event)
{
    (void)itf;
    int dtr = event->line_state_changed_data.dtr;
    int rts = event->line_state_changed_data.rts;
    // if (dtr && rts)                                   ///thinking why enable rts not success?
    if (dtr)
    {
        // ZYP_DEBUG_USB("Host opened the serial port\n");
        host_connected = true;
    }

    else
    {
        // ZYP_DEBUG_USB("Host closed the serial port\n");
        host_connected = false;
    }
}

/**
 * @name:
 * @msg:
 * @param {int} itf
 * @param {cdcacm_event_t} *event
 * @return {*}
 */
void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event)
{
    if (event->type == CDC_EVENT_RX)
    {
        uint8_t buffer[TINYUSB_RECIVE_BUFFER_SIZE];
        esp_err_t ret = tinyusb_cdcacm_read(itf, buffer, sizeof(buffer), &bytes_read);
        front_4Byte = *(uint32_t *)buffer; /// this usb_mode little big_ endian usb_mode will chang                                                                                                         // todo jusy behand 4 byte is  0 00000001  00000002 is file usb_mode      if not is debug cmd usb_mode  or data usb_mode       add
                                           // ZYP_DEBUG_USB("front_4Byte:0x%lx\n", front_4Byte);

        ZYP_DEBUG_USB("usb evy: %02x %02x %02x %02x\n", buffer[0], buffer[1], buffer[2], buffer[3]);

#if IS_ENABLE_DEBUG
        for (size_t i = 0; i < bytes_read; i++)
        {
            if (i == 0)
                ZYP_DEBUG_USB("origanl buffer:\t");
            ZYP_DEBUG_USB("0x%02x ", buffer[i]);
            if (i == bytes_read - 1)
                ZYP_DEBUG_USB("\n");
        }
        uint8_t *src = (uint8_t *)malloc(5);
        memcpy(src, buffer, 5);
        ZYP_DEBUG_USB("src:0x%x\n", *(unsigned int *)src);
        for (int i = 0; i < 5; i++)
        {
            ZYP_DEBUG_USB("src:0x%02x\n", src[i]);
            if (i == 5 - 1)
                ZYP_DEBUG_USB("\n");
        }
#endif
        //  uint32_t current_file_index = convert_to_big_endian(*front_4Byte);                                 //if not convert   0x00ccbbaa
        if (front_4Byte == LLF_FILE_START_BIT || front_4Byte == DNLD_FILE_START_BIT || front_4Byte == MAIN_FILE_START_BIT)
        {
            ZYP_DEBUG_USB("VIRGIN_FILE_MODE front_4Byte:0x%lx\n", front_4Byte);
            usb_mode = VIRGIN_FILE_MODE;
        }
        else if (MMMC_CMD_REQUEST_FREAM == bytes_read && buffer[MMMC_CMD_STATRT_BYTE] == MMMC_CMD_FREAM_START_BYTE && buffer[bytes_read - 1] == MMMC_CMD_FREAM_END_BYTE)
        {
            ZYP_DEBUG_USB("DEBUG_CMD_MODE\n");
            usb_mode = DEBUG_CMD_MODE;
        }
#if IS_ENABLE_CMD_DATA_DEBUG
        // else if (bytes_read >= TINY_USB_RECIVE_MAX_SIZE && usb_mode == DEBUG_CMD_MODE && buffer[MMMC_CMD_STATRT_BYTE] == MMC_DATA_CMD_FREAM_START_BYTE && buffer[MMMC_CMD_STATRT_BYTE + 1] == MMC_DATA_CMD_FREAM_TANSFER_HOST_TO_SLAVE_FLAG) /// usb_mode == DEBUG_CMD_MODE before send is CMD_FREAM（23） ,2: next recive data this else if  Theoretically come in once not enter twice
        else if (bytes_read >= TINY_USB_RECIVE_MAX_SIZE && buffer[MMMC_CMD_STATRT_BYTE] == MMC_DATA_CMD_FREAM_START_BYTE && buffer[MMMC_CMD_STATRT_BYTE + 1] == MMC_DATA_CMD_FREAM_TANSFER_HOST_TO_SLAVE_FLAG) // usb_mode == DEBUG_CMD_MODE before send is CMD_FREAM（23） ,2: next recive data this else if  Theoretically come in once not enter twice
        {
            ZYP_DEBUG_USB("DATA_CMD_MODE \n ");
            usb_mode = DATA_CMD_MODE;
#if 0
            data_cmd_cnt = buffer[MMMC_CMD_STATRT_BYTE + 3];
            rwRecivebuffer.startBit = buffer[MMMC_CMD_STATRT_BYTE];
            rwRecivebuffer.requestDirection = buffer[MMMC_CMD_STATRT_BYTE + 1];
            rwRecivebuffer.dataLength = buffer[MMMC_CMD_STATRT_BYTE + 2];
            ZYP_DEBUG_USB("heap_caps_malloc 0\n");
            cmd_data = heap_caps_malloc(data_cmd_cnt, MALLOC_CAP_SPIRAM); /// free（rwRecivebuffer.data） after the cmd transmission is completed.!!!!
            ZYP_DEBUG_USB("heap_caps_malloc 1\n");
            memcpy(cmd_data, buffer, bytes_read - MMC_DATA_CMD_BASIC_FREAM_SIZ);     /// Subtract 4 bytes       first copy  60bytes
            totall_bytes_received_data += bytes_read - MMC_DATA_CMD_BASIC_FREAM_SIZ; /// fist one is 64-4
#endif
        }
#endif

#if IS_ENABLE_RECIVE_RANDOEM_DATA
        else if ((RECIVE_BUFFER_SIZE_M >= bytes_read) && buffer[MMMC_CMD_STATRT_BYTE] == RANDOEM_DATA_STARTBIT && buffer[MMMC_CMD_STATRT_BYTE + 1] == RANDOEM_DATA_TANSFER_FLAG && buffer[MMMC_CMD_STATRT_BYTE + 2] == RANDOEM_DATA_FLAG && buffer[MMMC_CMD_STATRT_BYTE + 2 + buffer[MMMC_CMD_STATRT_BYTE + 3] + 2] == RANDOEM_DATA_END_BIT) ///+ 2  byte datalegth + last byte
        {
            ZYP_DEBUG_USB("Recivde_RANDOME_DATA_MOED\n");
            usb_mode = Recivde_RANDOME_DATA_MOED;
        }
#endif

        /// handle open or close button send aciss
        else if ((bytes_read == MMC_OPNE_BUTTON_FREAM && (buffer[MMMC_CMD_STATRT_BYTE] == MMC_OPNE_BUTTON_FREAM_FIRST_BYTE &&
                                                          buffer[MMMC_CMD_STATRT_BYTE + 1] == MMC_OPNE_BUTTON_FREAM_SCOND_BYTE && buffer[bytes_read - 1] == MMC_OPNE_BUTTON_FREAM_LAST_BYTE &&
                                                          buffer[bytes_read - 2] == MMC_OPNE_BUTTON_FREAM_LAST_BUTONE_BYTE)) ||
                 ((bytes_read == MMC_CLOSE_BUTTON_FREAM) && (buffer[MMMC_CMD_STATRT_BYTE] == MMC_CLOSE_BUTTON_FREAM_FIRST_BYTE &&
                                                             buffer[MMMC_CMD_STATRT_BYTE + 1] == MMC_CLOSE_BUTTON_FREAM_SCOND_BYTE && buffer[bytes_read - 1] == MMC_CLOSE_BUTTON_FREAM_LAST_BYTE && buffer[bytes_read - 2] == MMC_CLOSE_BUTTON_FREAM_LAST_BUTONE_BYTE)))
        {
            usb_mode = OTHER_MODE;
            ZYP_DEBUG_USB("OPEN_CLOSE_MODE\n"); /// Todo can optimize judge current_file_index which x has been download x file ，reset psram data and  current_file_index set zera
            return;
        }
#if IS_FILE_DEBUG
        else if (front_4Byte == DEBUG_FILE_START_BIT)
        {
            ZYP_DEBUG_USB("FILE_SCRIPT_MODE\n");
            usb_mode = FILE_SCRIPT_MODE;
            current_file_index = SCIRIPT_FILE; /// todo no influenc other mode change file_script_current_file_index?
        }
#endif

#if IS_FFU_MDDE
        else if (front_4Byte == FFU_FILE_START_BIT)
        {
            ZYP_DEBUG_USB("FFU_SCRIPT_MODE\n");
            usb_mode = FFU_FIEL_MODE;
            current_file_index = FFU_FILE; /// todo no influenc other mode change file_script_current_file_index?
        }
#endif

#if IS_SUPOORT_BUST_TEST
        else if (bytes_read == BUS_TEST_DATASIZE && buffer[MMMC_CMD_STATRT_BYTE] == MMC_DATA_CMD_FREAM_START_BYTE && buffer[bytes_read - 1] == MMC_DATA_CMD_FREAM_END_BYTE && front_4Byte == BUS_TEST_DATA_START_FLAG)
        {
            usb_mode = BUST_TEST_MODE;
        }
#endif

#if IS_SUPOORT_PROGRAM_CID_CSD
        else if (bytes_read == MMC_PROGRAM_CID_CSD_FREAM_DATASIZE && buffer[MMMC_CMD_STATRT_BYTE] == MMC_DATA_CMD_FREAM_START_BYTE && buffer[bytes_read - 1] == MMC_DATA_CMD_FREAM_END_BYTE && front_4Byte == MMC_PROGRAM_CID_CSD_START_FLAG)
        {
            usb_mode = PROGRAM_CID_CSD_MODE;
        }
#endif

        else if (bytes_read > 0) /// second revive file data--just b4 byte logical hangdle  or  recive other  unkonwn feam
        {
            if (usb_mode == VIRGIN_FILE_MODE)
            {
                usb_mode = VIRGIN_FILE_MODE;
            }
#if IS_ENABLE_CMD_DATA_DEBUG
            else if (usb_mode == DATA_CMD_MODE) /// next recive data_cmd fream handle    first recive 60byte copy to buffer second copy 64 byte
            {
                usb_mode = DATA_CMD_MODE;
            }
#endif
#if IS_FILE_DEBUG
            else if (usb_mode == FILE_SCRIPT_MODE)
            {
                usb_mode = FILE_SCRIPT_MODE;
            }
#endif

#if IS_FILE_DEBUG
            else if (usb_mode == FFU_FIEL_MODE)
            {
                usb_mode = FFU_FIEL_MODE;
            }
#endif

#if IS_ENABLE_RECIVE_RANDOEM_DATA
            else if (usb_mode == Recivde_RANDOME_DATA_MOED)
            {
                usb_mode = Recivde_RANDOME_DATA_MOED;
            }
#endif
            else
            {
                usb_mode = OTHER_MODE;
                return;
            }
        }

        if (usb_mode == VIRGIN_FILE_MODE)
        {
            if (ret == ESP_OK && bytes_read > 0)
            {
                if (!receiving_file)
                { /// ever file enter once
                    if (bytes_read >= FLIE_START_BIT)
                    {
                        esp_task_wdt_reset(); /// avoid progarm stack reboot
                        memcpy(&current_file_index, buffer, FLIE_START_BIT);
                        ZYP_DEBUG_USB("buffer_current_file_index = %08x\n", (unsigned int)current_file_index);
                        /// fetch current_file_index 4 byte  the last  one byte (00 or 01 or 02)
                        // uint8_t *current_file_index_=( uint32_t *)current_file_index;
                        // current_file_index=current_file_index_[3];
                        current_file_index = current_file_index & 0xFF000000; /// 02ccbbaa
                        ZYP_DEBUG_USB("current_file_index %08x\n", (unsigned int)current_file_index);
                        current_file_index %= MAX_FILES;
                        if (current_file_index == LLF_FILE || current_file_index == DNLD_FILE || current_file_index == MAIN_FILE)
                        {
                            ESP_LOGI(TAG, "Starting to receive file %ld", current_file_index);
                            receiving_file = true;
                            totall_bytes_received = 0; /// totall_bytes_received  no caculate startBit

                            dst = psram_base + current_file_index * FILE_SLOT_SIZE;
                            ZYP_DEBUG_USB("init psram_base:%p, dst:%p\n", psram_base, dst);
                            memcpy(dst, buffer + FLIE_START_BIT, bytes_read - FLIE_START_BIT); /// first copy 64-FLIE_START_BIT byte 60  to psram start location
                            totall_bytes_received = bytes_read - FLIE_START_BIT;               /// next psram index

                            ZYP_DEBUG_USB("Starting to receive file %ld,point psram :%p\n", current_file_index, dst);
                        }
                    }
                }
                else
                {
                    if (current_file_index == LLF_FILE || current_file_index == DNLD_FILE || current_file_index == MAIN_FILE)
                    {
                        /// recive next data
                        dst = psram_base + current_file_index * FILE_SLOT_SIZE + totall_bytes_received; /// the second enter   psram potint：psram_base+0+1020  ，totall_bytes_received  evertime is add The last time
                        memcpy(dst, buffer, bytes_read);
                        totall_bytes_received += bytes_read;
#if N0_USB_FIEL_SEND
                        uint8_t *last_8_bytes = dst + totall_bytes_received - 8;
                        ZYP_DEBUG_USB("Last 8 bytes: ");
                        for (int i = 0; i < 8; i++)
                        {
                            ZYP_DEBUG_USB("%02X ", last_8_bytes[i]);
                        }
                        ZYP_DEBUG_USB("\n");
#endif

#if N0_USB_FIEL_SEND
                        ESP_LOGI(TAG, "Received %zu bytes for file %ld, total: %zu Bytes, total: %zu KB",
                                 bytes_read, current_file_index, totall_bytes_received, totall_bytes_received / 1024);
#endif

#if USB_FIEL_SEND
                        if (bytes_read == 8 && current_file_index == 0)
                        {
#if N0_USB_FIEL_SEND
                            ZYP_DEBUG_USB("dst:%p\n", dst);
                            for (size_t i = 0; i < bytes_read; i++)
                            {
                                ZYP_DEBUG_USB("%02X ", *dst++); /// x x x x aa aa aa aa
                            }
                            ZYP_DEBUG_USB("\n");
                            ZYP_DEBUG_USB("totall_bytes_received:%d\n", totall_bytes_received); /// llf_file_size+8

#if 0
                            /// totall_bytes_received  first file 28164   startbit：4bit（no add） endbit：4bit(add 4bit)  file size：28164-FLIE_START_BIT=28160  27KB
                            ZYP_DEBUG_USB("\n ------------addr dest:%p , totall_bytes_received size:%dd----------------\n", dst, totall_bytes_received);
                            uint8_t *last_4_bytes = (uint8_t *)(dst + FLIE_START_BIT);
                            ZYP_DEBUG_USB("addr last_4_bytes :%p\n", last_4_bytes);
                            for (int i = 0; i < FLIE_START_BIT; i++)
                            {
                                ZYP_DEBUG_USB("%02X ", last_4_bytes[i]);
                            }
                            // uint8_t* file_start = psram_base + 28164-8;           ///0x3c037884
                            uint8_t *file_start = psram_base + 28160 - FLIE_START_BIT;
                            ZYP_DEBUG_USB("addr file start:%p\n", file_start);
                            for (int i = 0; i < 8; i++)
                            {
                                ZYP_DEBUG_USB("%02X ", file_start[i]);
                            }
                            ZYP_DEBUG_USB("\n-----------last 8 byte is----------------:\n");
                            for (int i = 0; i < bytes_read; i++)
                            {
                                ZYP_DEBUG_USB("%02X ", buffer[i]);
                            }
#endif
#endif

#if N0_USB_FIEL_SEND
                            /// print all data  can use usb or serial
                            // uint8_t *file_start = (uint8_t *)SAVA_LLF_FILE_STARTADDR;
                            uint8_t *file_start = psram_base;
                            ZYP_DEBUG_USB("addr file_start: %p\n", file_start);
                            for (int i = 0; i < LLF_FILE_SIZE; i++)
                            {
                                ZYP_DEBUG_USB("%02x", file_start[i]);
                                if (i == LLF_FILE_SIZE - 1)
                                {
                                    ZYP_DEBUG_USB("\n");
                                }
                            }

#endif
                        }
#endif

#if N0_USB_FIEL_SEND /// last receive  flie
                        if (bytes_read == 8 && current_file_index == 1 && (totall_bytes_received / 1024 == DNLD_FILE_SIZE_KB))
                        {
                            ZYP_DEBUG_USB("recive second file over\n");
                            ZYP_DEBUG_USB("\n ------------addr dest:%p , totall_bytes_received size:%dd----------------\n", dst, totall_bytes_received);
                            uint8_t *last_4_bytes = (uint8_t *)(dst + FLIE_START_BIT);
                            ZYP_DEBUG_USB("addr last_4_bytes :%p\n", last_4_bytes);
                            for (int i = 0; i < FLIE_START_BIT; i++)
                            {
                                ZYP_DEBUG_USB("%02X ", last_4_bytes[i]);
                            }
                        }
#endif

#if N0_USB_FIEL_SEND /// last receive  flie
                        if (bytes_read == 8 && current_file_index == 2 && (totall_bytes_received / 1024 == MAIN_FILE_SIZE))
                        {
                            ZYP_DEBUG_USB("recive lastest file over\n");
                            ZYP_DEBUG_USB("\n ------------addr dest:%p , totall_bytes_received size:%dd----------------\n", dst, totall_bytes_received);
                            uint8_t *last_4_bytes = (uint8_t *)(dst + FLIE_START_BIT);
                            ZYP_DEBUG_USB("addr last_4_bytes :%p\n", last_4_bytes);
                            for (int i = 0; i < FLIE_START_BIT; i++)
                            {
                                ZYP_DEBUG_USB("%02X ", last_4_bytes[i]);
                            }
                        }

#endif
                        if ((current_file_index == LLF_FILE && totall_bytes_received > LLF_FILE_SIZE - TINY_USB_RECIVE_MAX_SIZE) || (current_file_index == DNLD_FILE && totall_bytes_received > DNLD_FILE_SIZE - TINY_USB_RECIVE_MAX_SIZE) || (current_file_index == MAIN_FILE && totall_bytes_received > MAIN_FILE_SIZE_9050 - TINY_USB_RECIVE_MAX_SIZE))
                        // if (totall_bytes_received >= FLIE_START_BIT)
                        {
                            ZYP_DEBUG_USB("totall_bytes_received:%d\n", totall_bytes_received);
                            uint32_t marker;
                            // memcpy(&marker, dst + totall_bytes_received - FLIE_START_BIT, FLIE_START_BIT);               ///dst hava been shift not add  totall_bytes_received
                            memcpy(&marker, dst + FLIE_START_BIT, FLIE_START_BIT); /// for exmple last dst 0x3c037888
                            // ZYP_DEBUG_USB("marker:%lx ", marker);
                            // ZYP_DEBUG_USB("\n");
                            if (marker == FIEL_END_MARKER) /// todo 优化 ever file endbit mybe differt
                            {
                                ESP_LOGI(TAG, "File %ld received completely, total: %zu KB,size: %d Byte\n",
                                         current_file_index, totall_bytes_received / 1024, totall_bytes_received);

                                // current_file_index++;
                                if (current_file_index == LLF_FILE)
                                {
#if VIGINAL_MODE_HARD_STARTBIT_NO_FILE_SIZE

                                    virigin_file_size_t.llf_file_size = totall_bytes_received - FLIE_END_BIT;
                                    ZYP_DEBUG("virigin_file_size_t.llf_file_size:%d\n", virigin_file_size_t.llf_file_size);
#endif
                                    current_file_index = DNLD_FILE;
                                }

                                else if (current_file_index == DNLD_FILE)
                                {
#if VIGINAL_MODE_HARD_STARTBIT_NO_FILE_SIZE
                                    virigin_file_size_t.dnld_file_size = totall_bytes_received - FLIE_END_BIT;
                                    ZYP_DEBUG("virigin_file_size_t.dnld_file_size:%d\n", virigin_file_size_t.dnld_file_size);
#endif
                                    current_file_index = MAIN_FILE;
                                }

                                else if (current_file_index == MAIN_FILE)
                                {
#if VIGINAL_MODE_HARD_STARTBIT_NO_FILE_SIZE
                                    virigin_file_size_t.main_file_size = totall_bytes_received - FLIE_END_BIT;
                                    ZYP_DEBUG("virigin_file_size_t.main_file_size:%d\n", virigin_file_size_t.main_file_size);
#endif
                                    current_file_index = MAIN_FILE_Done;
                                }

                                totall_bytes_received = 0;
                                receiving_file = false;
                                bytes_read = 0;
                                usb_mode = OTHER_MODE; /// optimast do not effect  random add
                                if (current_file_index >= MAX_FILES)
                                {
                                    ESP_LOGI(TAG, "All files received.");
                                }
                            }
                        }
                    }
                }
            }
        } //// if(usb_mode==VIRGIN_FILE_MODE)
#if IS_ENABLE_CMD_DATA_DEBUG
        else if (usb_mode == DEBUG_CMD_MODE)
        {
            memcpy(&requestbuffer, buffer, bytes_read);
            // if (xQueueSendFromISR(usb_cmd_queue, &requestbuffer, NULL) != pdTRUE)
            if (xQueueSend(usb_cmd_queue, &requestbuffer, pdMS_TO_TICKS(50)) != pdTRUE)
            // if (xQueueSend(usb_cmd_queue, &requestbuffer, 0) != pdTRUE)
            {
                ZYP_DEBUG_USB("Failed to send to usb_cmd_queue\n");
            }
            ZYP_DEBUG_USB("Send CMD Fream to Handled\n");
        }
        else if (usb_mode == DATA_CMD_MODE) /// second begain run  this  RECIVE BUFFER 64 lastend recive 4 byte end mark
        {
            if (!usb_data_send_flag)
            {
                ZYP_DEBUG_DATA("-----------once recive origin data buffer-----------\n");
                for (size_t i = 0; i < bytes_read; i++)
                {
                    ZYP_DEBUG_DATA("%02x ", buffer[i]);
                }
                ZYP_DEBUG_USB("\n");

                data_cmd_cnt = buffer[MMMC_CMD_STATRT_BYTE + 3];
                rwRecivebuffer.startBit = buffer[MMMC_CMD_STATRT_BYTE];
                rwRecivebuffer.requestDirection = buffer[MMMC_CMD_STATRT_BYTE + 1];
                rwRecivebuffer.rwFlag = buffer[MMMC_CMD_STATRT_BYTE + 2];
                rwRecivebuffer.dataLength = buffer[MMMC_CMD_STATRT_BYTE + 3];
                ZYP_DEBUG_USB("buffer[3]:%d,  data_cmd_cnt:%d, writeMultipeCount:%d rwRecivebuffer.dataLength:%d\n", buffer[3], data_cmd_cnt, writeMultipeCount, (int)rwRecivebuffer.dataLength);

                // cmd_data = heap_caps_malloc(data_cmd_cnt, MALLOC_CAP_SPIRAM); /// free（rwRecivebuffer.data） after the cmd transmission is completed.!!!!
                cmd_data = heap_caps_malloc(writeMultipeCount * EXT_CSD_MMC_SIZE, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
                //    cmd_data = heap_caps_malloc(data_cmd_cnt, MALLOC_CAP_DMA);
                // if (data_cmd_cnt <= 512)
                // {
                //     cmd_data = heap_caps_malloc(data_cmd_cnt, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);  ///inter memory
                // }
                // else
                // {
                //     cmd_data = heap_caps_malloc(data_cmd_cnt, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);   ///psram memory
                // }
                ZYP_DEBUG_USB("123\n ");
                memcpy(cmd_data, buffer + MMC_DATA_CMD_BASIC_FREAM_SIZ, bytes_read - MMC_DATA_CMD_BASIC_FREAM_SIZ); /// memcpy(cmd_data... mesan index memcpy(cmd_data+0..   Subtract 4 bytes       first copy  60bytes
                totall_bytes_received_data += bytes_read - MMC_DATA_CMD_BASIC_FREAM_SIZ;                            /// fist one is 64-4
                usb_data_send_flag = true;
            }
            else
            {
                ZYP_DEBUG_DATA("-----------second recive origin data buffer-----------\n");
                for (size_t i = 0; i < bytes_read; i++)
                {
                    ZYP_DEBUG_DATA("%02x ", buffer[i]);
                }
                ZYP_DEBUG_DATA("\n");
                if (bytes_read >= RECIVE_BUFFER_SIZE_M) /// midel hanlde
                {
                    // memcpy(cmd_data, buffer, bytes_read);
                    memcpy(cmd_data + totall_bytes_received_data, buffer, bytes_read);
                    // memcpy(cmd_data+totall_bytes_received_data+1, buffer, bytes_read);
                    totall_bytes_received_data += bytes_read; /// everytime recive 64byte  so 512  of multiple   first totall_bytes_received_data 60 BYTE 第二次bytes_read 循环512/64=8 接受8此之后，刚好收完data数据，下次在接受只是4个byte结束位
                    if (totall_bytes_received_data / EXT_CSD_MMC_SIZE == data_cmd_cnt && totall_bytes_received_data % EXT_CSD_MMC_SIZE == 0)
                    {

                        ZYP_DEBUG_DATA("data recive over\n");
                        for (size_t i = 0; i < totall_bytes_received_data; i++)
                        {
                            ZYP_DEBUG_DATA("%02x ", cmd_data[i]);
                        }
                        ZYP_DEBUG_DATA("\n");
                    }
                }
                else if (bytes_read == MMC_DATA_CMD_FREAM_LAST_SIZE && buffer[bytes_read - 1] == MMC_DATA_CMD_FREAM_END_BYTE)
                {
                    // memset(cmd_data,buffer,bytes_read-1);
                    memcpy(cmd_data + totall_bytes_received_data, buffer, bytes_read - 1);
                    totall_bytes_received_data += bytes_read - 1;
                    /// data recive over
                    rwRecivebuffer.data = cmd_data; /// in  send cmd after must be free！！！

                    ZYP_DEBUG_USB("buffer  endmark:\n");
                    for (uint8_t i = 0; i < MMC_DATA_CMD_FREAM_LAST_SIZE; i++)
                    {
                        ZYP_DEBUG_USB("%02x  ", buffer[i]);
                        if (i == MMC_DATA_CMD_FREAM_LAST_SIZE - 1)
                        {
                            ZYP_DEBUG_USB("\n");
                        }
                    }
                    // usb_data_send_flag = false;      ///location in hanlde cmd fream also right.
                }
            }
        }
#endif

#if IS_SUPOORT_BUST_TEST
        else if (usb_mode == BUST_TEST_MODE)
        {
            data_cmd_cnt = buffer[MMMC_CMD_STATRT_BYTE + 3];
            rwRecivebuffer.startBit = buffer[MMMC_CMD_STATRT_BYTE];
            rwRecivebuffer.requestDirection = buffer[MMMC_CMD_STATRT_BYTE + 1];
            rwRecivebuffer.rwFlag = buffer[MMMC_CMD_STATRT_BYTE + 2];
            rwRecivebuffer.dataLength = buffer[MMMC_CMD_STATRT_BYTE + 3];
            ZYP_DEBUG_USB("buffer[3]:%d,  data_cmd_cnt:%d, rwRecivebuffer.dataLength:%d\n", buffer[3], data_cmd_cnt, (int)rwRecivebuffer.dataLength);

            cmd_data = heap_caps_malloc(data_cmd_cnt * EXT_CSD_MMC_SIZE, MALLOC_CAP_SPIRAM);
            // cmd_data = heap_caps_malloc(data_cmd_cnt, MALLOC_CAP_DMA | MALLOC_CAP_8BIT);   ///TODO MALLOC_CAP_DMA | MALLOC_CAP_8BIT
            memcpy(cmd_data, buffer + MMC_DATA_CMD_BASIC_FREAM_SIZ, sizeof(unsigned int));
            rwRecivebuffer.data = cmd_data;
            usb_mode = OTHER_MODE;
        }
#endif

#if IS_SUPOORT_PROGRAM_CID_CSD
        else if (usb_mode == PROGRAM_CID_CSD_MODE)
        {
            ZYP_DEBUG_USB("PROGRAM_CID_CSD_MODE \n ");
            rwRecivebuffer.startBit = buffer[MMMC_CMD_STATRT_BYTE];
            rwRecivebuffer.requestDirection = buffer[MMMC_CMD_STATRT_BYTE + 1];
            rwRecivebuffer.rwFlag = buffer[MMMC_CMD_STATRT_BYTE + 2];
            rwRecivebuffer.dataLength = buffer[MMMC_CMD_STATRT_BYTE + 3];
            ZYP_DEBUG_USB("buffer[3]:%d,rwRecivebuffer.dataLength:%d\n", buffer[3], (int)rwRecivebuffer.dataLength);

            cmd_data = heap_caps_malloc(rwRecivebuffer.dataLength * EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
            memcpy(cmd_data, buffer + MMC_DATA_CMD_BASIC_FREAM_SIZ, sizeof(unsigned int) * sizeof(unsigned int));
            rwRecivebuffer.data = cmd_data;
            usb_mode = OTHER_MODE;
        }
#endif

#if IS_FFU_MDDE
        if (usb_mode == FFU_FIEL_MODE) /// debugbin file
        {
            if (ret == ESP_OK && bytes_read > 0)
            {
                /// 1.  run ponce , evertime recive (tinyusb-recive-maxe 64) byte ,record file header file_size in global var  ,recive byte siee in totall_bytes_received
                if (!receiving_file)
                {
                    if (bytes_read >= (FLIE_START_BIT * 2)) /// headr 4 byte + 4 bye filesize
                    {
                        esp_task_wdt_reset();
                        memcpy(&ffu_file_index_startbit, buffer, FLIE_START_BIT);
                        memcpy(&virigin_file_size_t.ffu_file_size,
                               buffer + FLIE_START_BIT, FLIE_START_BIT);
                        ZYP_DEBUG_MMC("Start bit: %08lx, File size: %d bytes\n",
                                      ffu_file_index_startbit, virigin_file_size_t.ffu_file_size);

                        if (current_file_index == FFU_FILE &&
                            ffu_file_index_startbit == FFU_FILE_START_BIT)
                        {
                            receiving_file = true;
                            totall_bytes_received = 0;
                            dst = psram_base + current_file_index * FILE_SLOT_SIZE;

                            size_t first_chunk_size = bytes_read - (FLIE_START_BIT * 2);
                            memcpy(dst, buffer + (FLIE_START_BIT * 2), first_chunk_size);
                            totall_bytes_received = first_chunk_size;
                            
                            ZYP_DEBUG_MMC("Started receiving file %ld. Initial size: %zu bytes\n",
                                          current_file_index, first_chunk_size);
                        }
                    }
                }

                else
                {
                    if (current_file_index == FFU_FILE)
                    {
                        uint8_t *current_dst = dst + totall_bytes_received;
                        memcpy(current_dst, buffer, bytes_read);
                        totall_bytes_received += bytes_read;
                        ZYP_DEBUG_USB("Received chunk: %zu bytes, Total: %zu/%u bytes\n",
                                      bytes_read, totall_bytes_received,
                                      virigin_file_size_t.ffu_file_size);
                        if (totall_bytes_received >= virigin_file_size_t.ffu_file_size) /// recive over juge
                        {
                            uint32_t end_marker;
                            memcpy(&end_marker, dst + virigin_file_size_t.ffu_file_size, FLIE_START_BIT);
                            ZYP_DEBUG_MMC("End marker: %08lx\n", end_marker);
                            if (end_marker == FIEL_END_MARKER)
                            {
                                ESP_LOGI(TAG, "File %ld received successfully! Size: %zu bytes",
                                         current_file_index, totall_bytes_received);
                                ffu_binfile_reciveover = true;
                                receiving_file = false;
                                totall_bytes_received = 0;
                                usb_mode = OTHER_MODE;
                                ZYP_DEBUG_MMC("_dst: %0x\n", dst[virigin_file_size_t.ffu_file_size - 1]);
                                ZYP_DEBUG_MMC("_dst: %0x\n", dst[virigin_file_size_t.ffu_file_size]);
                            }
                            else
                            {
                                ESP_LOGE(TAG, "Invalid end marker: %08lx", end_marker);
                                receiving_file = false;
                                totall_bytes_received = 0;
                            }
                        }
                    }
                }
            }
        }
#endif

#if IS_FILE_DEBUG
        if (usb_mode == FILE_SCRIPT_MODE) /// debugbin file
        {
            if (ret == ESP_OK && bytes_read > 0)
            {
                if (!receiving_file)
                {
                    if (bytes_read >= (FLIE_START_BIT * 2))
                    {
                        esp_task_wdt_reset();
                        memcpy(&debug_file_index_startbit, buffer, FLIE_START_BIT);
                        memcpy(&virigin_file_size_t.debug_file_size,
                               buffer + FLIE_START_BIT, FLIE_START_BIT);

                        ZYP_DEBUG_USB("Start bit: %08lx, File size: %d bytes\n",
                                      debug_file_index_startbit, virigin_file_size_t.debug_file_size);

                        if (current_file_index == SCIRIPT_FILE &&
                            debug_file_index_startbit == DEBUG_FILE_START_BIT)
                        {
                            receiving_file = true;
                            totall_bytes_received = 0;
                            dst = psram_base + current_file_index * FILE_SLOT_SIZE;

                            size_t first_chunk_size = bytes_read - (FLIE_START_BIT * 2);
                            memcpy(dst, buffer + (FLIE_START_BIT * 2), first_chunk_size);
                            totall_bytes_received = first_chunk_size;

                            ZYP_DEBUG_USB("Started receiving file %ld. Initial size: %zu bytes\n",
                                          current_file_index, first_chunk_size);
                        }
                    }
                }
                else
                {
                    if (current_file_index == SCIRIPT_FILE)
                    {
                        uint8_t *current_dst = dst + totall_bytes_received;
                        memcpy(current_dst, buffer, bytes_read);
                        totall_bytes_received += bytes_read;
                        ZYP_DEBUG_USB("Received chunk: %zu bytes, Total: %zu/%u bytes\n",
                                      bytes_read, totall_bytes_received,
                                      virigin_file_size_t.debug_file_size);
                        if (totall_bytes_received >= virigin_file_size_t.debug_file_size)
                        {
                            uint32_t end_marker;
                            memcpy(&end_marker, dst + virigin_file_size_t.debug_file_size, FLIE_START_BIT);
                            ZYP_DEBUG_USB("End marker: %08lx\n", end_marker);
                            if (end_marker == FIEL_END_MARKER)
                            {
                                ESP_LOGI(TAG, "File %ld received successfully! Size: %zu bytes",
                                         current_file_index, totall_bytes_received);
                                debugbinfile_reciveover = true;
                                receiving_file = false;
                                totall_bytes_received = 0;
                                usb_mode = OTHER_MODE;
                                ZYP_DEBUG_USB("_dst: %0x\n", dst[virigin_file_size_t.debug_file_size - 1]);
                                ZYP_DEBUG_USB("_dst: %0x\n", dst[virigin_file_size_t.debug_file_size]);
                            }
                            else
                            {
                                ESP_LOGE(TAG, "Invalid end marker: %08lx", end_marker);
                                receiving_file = false;
                                totall_bytes_received = 0;
                            }
                        }
                    }
                }
            }
        }
#endif

#if IS_ENABLE_RECIVE_RANDOEM_DATA
        if (usb_mode == Recivde_RANDOME_DATA_MOED)
        {
            ZYP_DEBUG_USB("Recivde_RANDOME_DATA_MOED \n ");
            rwRecivebuffer.startBit = buffer[MMMC_CMD_STATRT_BYTE]; /// BA 00 AA  datasize
            rwRecivebuffer.requestDirection = buffer[MMMC_CMD_STATRT_BYTE + 1];
            rwRecivebuffer.rwFlag = buffer[MMMC_CMD_STATRT_BYTE + 2];
            rwRecivebuffer.dataLength = buffer[MMMC_CMD_STATRT_BYTE + 3];
            ZYP_DEBUG_USB("buffer[3]:%d,rwRecivebuffer.dataLength:%d\n", buffer[3], (int)rwRecivebuffer.dataLength);

            cmd_data = heap_caps_malloc(rwRecivebuffer.dataLength, MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
            memcpy(cmd_data, buffer + MMC_DATA_CMD_BASIC_FREAM_SIZ, rwRecivebuffer.dataLength);
            rwRecivebuffer.data = cmd_data;
            usb_mode = OTHER_MODE;
        }
#endif
    }

#if N0_USB_FIEL_SEND
    void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event)
    {
        if (event->type == CDC_EVENT_RX)
        {
            uint8_t buffer[1024];
            size_t bytes_read = 0;
            esp_err_t ret = tinyusb_cdcacm_read(itf, buffer, sizeof(buffer), &bytes_read);

            if (ret == ESP_OK && bytes_read > 0)
            {
                ESP_LOGI(TAG, "Received %zu bytes of data:", bytes_read);
                for (size_t i = 0; i < bytes_read; i++)
                {
                    ESP_LOGI(TAG, "%02x ", buffer[i]); ///
                }
                ESP_LOGI(TAG, "\n");

                // size_t queued_bytes = tinyusb_cdcacm_write_queue(itf, buffer, bytes_read);
                // if (queued_bytes != bytes_read) {
                //     ESP_LOGE(TAG, "Failed to queue all received data back, queued %zu bytes", queued_bytes);
                // }
                // esp_err_t flush_result = tinyusb_cdcacm_write_flush(itf, 0); // 非阻塞模式
                // if (flush_result != ESP_OK) {
                //     ESP_LOGE(TAG, "Failed to flush data, error: %d", flush_result);
                // }
            }
        }
    }
#endif
}
/**
 * @name:
 * @msg:
 * @param {int} fileIndex
 * @return {*}
 */
void print_file_hex(int fileIndex)
{
    uint8_t *file_start = psram_base + fileIndex * FILE_SLOT_SIZE;
    ZYP_DEBUG_USB("------------------- %d file_start:%p---------\n", fileIndex, file_start);
    // if (1==fileIndex || 2==fileIndex ||  0==fileIndex)
    // {
    for (int i = 0; i < 1024 * 5; i++)
    { /// 打印文件前32byte  check
        ZYP_DEBUG_USB("%02X ", file_start[i]);
    }
    // }else{
    //      return;
    // }
    ZYP_DEBUG_USB("\n");
}

/**
 * @name:
 * @msg:
 * @return {*}
 */
void init_tud_usb_usart_psram(void)
{
    ESP_LOGE(TAG, "--------------------------------------------------");
    ESP_LOGI(TAG, "USB initialization");

    const tinyusb_config_t tusb_cfg = {
        .device_descriptor = NULL,
        .string_descriptor = NULL,
        .external_phy = false,
        .configuration_descriptor = NULL,
    };

    ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));

    tinyusb_config_cdcacm_t acm_cfg = {
        .usb_dev = TINYUSB_USBDEV_0,
        .cdc_port = TINYUSB_CDC_ACM_0,
        .rx_unread_buf_sz = 512,
        .callback_rx = tinyusb_cdc_rx_callback,
        .callback_rx_wanted_char = NULL,
        .callback_line_state_changed = tinyusb_cdc_line_state_callback,
        .callback_line_coding_changed = NULL};

    ESP_ERROR_CHECK(tusb_cdc_acm_init(&acm_cfg));
    // ESP_ERROR_CHECK(tinyusb_cdcacm_register_callback(TINYUSB_CDC_ACM_0, CDC_EVENT_LINE_STATE_CHANGED, &tinyusb_cdc_rx_callback));
    ESP_ERROR_CHECK(tinyusb_cdcacm_register_callback(TINYUSB_CDC_ACM_0, CDC_EVENT_RX_WANTED_CHAR, &tinyusb_cdc_rx_callback));
    ESP_ERROR_CHECK(tinyusb_cdcacm_register_callback(TINYUSB_CDC_ACM_0, CDC_EVENT_LINE_STATE_CHANGED, &tinyusb_cdc_line_state_callback));
    ESP_LOGI(TAG, "USB initialization DONE");

    ESP_LOGI(TAG, "ESP_PSRAM initialization");
    // INIT PSRAM（IF NOT INIT）           add init no sucess?
    // esp_err_t ret = esp_psram_init();  ///esp_psram_is_initialized() implicit init PSRAM，But explicit initialization is a good practice? no need explicit init
    // if (ret != ESP_OK) {
    // ESP_LOGE(TAG, "Failed to initialize PSRAM: %s", esp_err_to_name(ret));
    //     return;
    // }
    if (esp_psram_is_initialized()) /// esp_psram_init
    {
        ZYP_DEBUG_USB("PSRAM is enabled.\n");
        // get PSRAM SIZE
        size_t psram_size = esp_psram_get_size();
        ZYP_DEBUG_USB("PSRAM size: %u bytes\n", psram_size);

        size_t psram_total = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
        size_t psram_free = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
        ZYP_DEBUG_USB("Total PSRAM: %d bytes\n", psram_total);
        ZYP_DEBUG_USB("Free PSRAM: %d bytes\n", psram_free);
    }
    else
    {
        ZYP_DEBUG_USB("PSRAM is not enabled.\n");
        return;
    }
    // rx_buf = (uint8_t *)heap_caps_malloc(FILE_SLOT_SIZE, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM);
    // // rx_buf = (uint8_t *)malloc(FILE_SLOT_SIZE);
    // if (!rx_buf)
    // {
    //     ESP_LOGE(TAG, "Failed to allocate memory for rx_buf");
    //     return;
    // }
    // else
    // {
    //     ESP_LOGE(TAG, "SUCCESS allocate memory for rx_buf");
    // }
    ZYP_DEBUG_USB(".esp_get_free_heap_size = %ld\n\r", esp_get_free_heap_size());
    ESP_LOGI(TAG, "ESP_PSRAM DONE");
}

void zyp_tinyusb_cdcacm_write_queue(uint8_t itf, uint8_t *write_buffer, size_t write_size)
{
    const size_t m_chunk_size = TINY_USB_WRITE_SIZE; // Match TinyUSB buffer size
    size_t remaining = write_size;
    size_t offset = 0;

    while (remaining > 0)
    {
        size_t chunk_size = (remaining > m_chunk_size) ? m_chunk_size : remaining;
        size_t queued = tinyusb_cdcacm_write_queue(itf, write_buffer + offset, chunk_size);

        if (queued > 0)
        {
            offset += queued;
            remaining -= queued;
        }
        // Flush after each chunk to avoid buffer overflow
        esp_err_t err = tinyusb_cdcacm_write_flush(itf, pdMS_TO_TICKS(100));
        if (err != ESP_OK)
        {
            ZYP_DEBUG_USB("Failed to flush data over USB: %s\n", esp_err_to_name(err));
            break;
        }
    }
    ZYP_DEBUG_USB("Total flushed %zu bytes\n", offset);
#if IS_ENABLEN_SECOND_RESOVTION
    size_t queued = tinyusb_cdcacm_write_queue(itf, write_buffer, write_size);
    if (queued != write_size)
    {
        ZYP_DEBUG_USB("Only %zu of %zu bytes queued\n", queued, write_size);
    }
    //// flush buffer block wait max 10ms
    esp_err_t err = tinyusb_cdcacm_write_flush(itf, pdMS_TO_TICKS(100));
    if (err != ESP_OK)
    {
        ZYP_DEBUG_USB("Failed to flush data over USB: %s\n", esp_err_to_name(err));
        return;
    }
    else
        ZYP_DEBUG_USB("Flushed %zu bytes\n", queued);
#endif
}

bool zyp_tud_cdc_connected(void)
{
    return tud_cdc_connected();
}

void zyp_finall_tinyusb_cdcacm_write_queue(uint8_t itf, uint8_t *write_buffer, size_t write_size)
{
    ZYP_DEBUG_USB("Writing %d bytes to USB\n", write_size);
    uint32_t timeout_ms = 10000; // detect timeout 10s
    uint32_t start = xTaskGetTickCount();
    while (!host_connected)
    {
        vTaskDelay(pdMS_TO_TICKS(100));
        if ((xTaskGetTickCount() - start) * portTICK_PERIOD_MS > timeout_ms)
        {
            ZYP_DEBUG_USB("Timeout waiting for host connectionz\n");
            break;
        }
    }
    if (host_connected)
    {
        if (zyp_tud_cdc_connected())
        {
            ZYP_DEBUG_USB("write_size:%d\n", write_size);
            zyp_tinyusb_cdcacm_write_queue(itf, (const uint8_t *)write_buffer, write_size);
        }
        else
        {
            ZYP_DEBUG_USB("Waiting for USB connection...\n");
        } // }
    }
}